export class AStarNode {
  public g: number = 0; // 从起点到当前节点的实际代价
  public h: number = 0; // 从当前节点到终点的启发式估计代价
  public f: number = 0; // 总代价 f = g + h
  public parent: AStarNode | null = null; // 回溯路径的父节点

  constructor(
    public readonly x: number, // 节点在网格中的 x 坐标
    public readonly y: number, // 节点在网格中的 y 坐标
    public readonly walkable: boolean = true // 是否可通行（默认true）
  ) {
    this.g = 0;
    this.h = 0;
    this.f = 0;
    this.parent = null;
  }
}


import { EventTarget } from 'cc';

// A* 寻路类
export class AStarPathfinder {
  private grid: AStarNode[][]; // 二维网格数组
  private openList: AStarNode[] = []; // 待检查节点列表
  public closedList: Set<AStarNode> = new Set(); // 已检查节点集合
  private eventTarget: EventTarget;

  // 初始化网格 (0 表示可通行，1 表示障碍物)
  constructor(grid: number[][], _eventTarget: EventTarget) {
    this.grid = [];
    for (let y = 0; y < grid.length; y++) {
      this.grid[y] = [];
      for (let x = 0; x < grid[y].length; x++) {
        this.grid[y][x] = new AStarNode(x, y, grid[y][x] === 0);
      }
    }

    this.eventTarget = _eventTarget;
  }

  // 计算两个节点之间的曼哈顿距离（启发式函数）
  private heuristic(nodeA: AStarNode, nodeB: AStarNode): number {
    return (Math.abs(nodeA.x - nodeB.x) + Math.abs(nodeA.y - nodeB.y))*2;
  }

  // 获取节点的相邻节点（四方向）
  private getNeighbors(node: AStarNode): AStarNode[] {
    const neighbors: AStarNode[] = [];
    const directions = [
      [0, -1], // 上
      [1, 0],  // 右
      [0, 1],  // 下
      [-1, 0]  // 左
    ];

    for (const [dx, dy] of directions) {
      const x = node.x + dx;
      const y = node.y + dy;

      // 检查边界
      if (y >= 0 && y < this.grid.length && x >= 0 && x < this.grid[0].length) {
        const neighbor = this.grid[y][x];
        if (neighbor.walkable) {
          neighbors.push(neighbor);
        }
      }
    }

    return neighbors;
  }

  // 寻找从起点到终点的路径
  public async findPath(startX: number, startY: number, endX: number, endY: number): Promise<[number, number][]> {
    const startNode = this.grid[startY][startX];
    const endNode = this.grid[endY][endX];

    // 验证起点和终点
    if (!startNode.walkable || !endNode.walkable) {
      return [];
    }

    // 初始化开放列表（添加起点）
    this.openList = [startNode];
    this.closedList = new Set();

    while (this.openList.length > 0) {
      // 获取 F 值最低的节点
      let currentNode = this.openList[0];
      let currentIndex = 0;

      for (let i = 1; i < this.openList.length; i++) {
        if (this.openList[i].f < currentNode.f) {
          currentNode = this.openList[i];
          currentIndex = i;
        }
      }

      // 找到终点，回溯生成路径
      if (currentNode === endNode) {
        const path: [number, number][] = [];
        const resultNode=new Array<AStarNode>();
        let current: AStarNode | null = currentNode;
        while (current !== null) {
          path.push([current.x, current.y]);
          resultNode.push(current);
          current = current.parent;
        }
        this.eventTarget.emit('result', resultNode);
        await this.Sleep(20);
        var result =path.reverse();
        return result; // 反转路径（起点→终点）

      }

      // 将当前节点移出开放列表，加入关闭列表
      this.openList.splice(currentIndex, 1);
      this.closedList.add(currentNode);

      this.eventTarget.emit('realPath', currentNode);
      await this.Sleep(20);


      // 处理相邻节点
      const neighbors = this.getNeighbors(currentNode);
      for (const neighbor of neighbors) {
        // 跳过已处理的节点
        if (this.closedList.has(neighbor)) continue;

        this.eventTarget.emit('path', neighbor);
        await this.Sleep(20);

        // 计算新的 G 值（当前节点的 G 值 + 1）
        const gScore = currentNode.g + 1;

        // 检查是否找到更优路径
        let isBetterPath = false;
        if (!this.openList.includes(neighbor)) {
          // 新发现的节点
          this.openList.push(neighbor);
          isBetterPath = true;
        } else if (gScore < neighbor.g) {
          // 已存在但找到了更优路径
          isBetterPath = true;
        }

        // 如果找到更优路径，更新节点信息
        if (isBetterPath) {
          neighbor.parent = currentNode;
          neighbor.g = gScore;
          neighbor.h = this.heuristic(neighbor, endNode);
          neighbor.f = neighbor.g + neighbor.h;
        }
      }
    }

    return []; // 未找到路径
  }

  Sleep(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}